#include"image.h"
//普通构造函数
Image::Image(int h, int w) :height(h), width(w)
{
    this->height = h;
    this->width = w;
    //为第一维分配空间
    data = new unsigned char** [h];
    //其大小为sizeof(unsigned char*) * bitmapinfoheader.biHeight，这点很容易错
    //申请行指针
    for (int i = 0; i < this->height; i++)
    {
        //注意3通道，每个像素3个字节
        data[i] = new unsigned char* [w];//为第二维分配空间
        for (int j = 0; j < this->width; j++)
        {
            data[i][j] = new unsigned char[3];//为第三维分配空间
            // 读取像素数据
            for (int k = 0; k < 3; k++) {
                data[i][j][k] = 0;
            }
        }
    }
}
Image::Image(int h, int w, unsigned char val)//创建的图像像素值都为val;
{
    this->height = h;
    this->width = w;
    //为第一维分配空间
    data = new unsigned char** [h];
    //其大小为sizeof(unsigned char*) * bitmapinfoheader.biHeight，这点很容易错
    //申请行指针
    for (int i = 0; i < this->height; i++)
    {
        //注意3通道，每个像素3个字节
        data[i] = new unsigned char* [w];//为第二维分配空间
        for (int j = 0; j < this->width; j++)
        {
            data[i][j] = new unsigned char[3];//为第三维分配空间
            // 读取像素数据
            for (int k = 0; k < 3; k++) {
                data[i][j][k] = val;
            }
        }
    }
}


//拷贝构造函数
Image::Image(Image& im)
{
    alloc(&im.data, height, width);
    im.bitmapinfoheader = bitmapinfoheader;
    im.bmpfileheader = bmpfileheader;
}

//析构函数
Image::~Image()
{
    myFree(&data, height, width);
}
//设置图像所有像素为同一值
void Image::Set(unsigned char value)
{
    int i, j, k;
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            for (k = 0; k < 3; k++)
            {
                data[i][j][k] = value;
            }
        }
    }
}


//false 左右，true 上下
void Image::Flip(int code)
{
    if (code)
    {
        for (int i = 0; i < height / 2; i++)
        {
            for (int j = 0; j < width; j++)
            {
                for (int k = 0; k < 3; k++)
                {
                    unsigned char t;
                    t = data[height - i - 1][j][k];
                    data[height - i - 1][j][k] = data[i][j][k];
                    data[i][j][k] = t;
                }
            }
        }
    }
    else
    {
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width / 2; j++)
            {
                for (int k = 0; k < 3; k++)
                {
                    unsigned char t;
                    t = data[i][width - j - 1][k];
                    data[i][width - j - 1][k] = data[i][j][k];
                    data[i][j][k] = t;
                }
            }
        }
    }
}


//图像缩小，放大
//false缩小,true放大
void Image::Resize(int code)
{
    unsigned char*** t_data;
    if (code)//放大
    {
        alloc(&t_data, height * 2, width * 2);
        for (int i = 0; i < height-1; i++)
        {
            for (int j = 0; j <width-1; j++)
            {
                for (int k = 0; k < 3; k++)
                {
                    t_data[2 * i][2 * j][k] = data[i][j][k];
                    t_data[2 * i][2 * j + 1][k] = data[i][j][k];
                    t_data[2 * i + 1][2 * i + 1][k] = data[i][j][k];
                    t_data[2 * i + 1][2 * j][k] = data[i][j][k];
                    
                }
            }
        }
        for (int i = 0; i < height*2; i++)
        {
            for (int j = 0; j < width*2; j++)
            {
                for (int k = 0; k < 3; k++)
                {
                    if (t_data[i][j][k] == 0)
                    {
                        t_data[i][j][k] = data[i / 2][j / 2][k];
                    }
                }
            }
        }
        height = height * 2;
        width = width * 2;
        bitmapinfoheader.biHeight *= 2;
        bitmapinfoheader.biWidth *= 2;
        bitmapinfoheader.biSizeImage *= 4;
        myFree(&data, height / 2, width / 2);
        alloc(&data, height, width);
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                for (int k = 0; k < 3; k++)
                {
                    data[i][j][k] = t_data[i][j][k];

                }
            }
        }
        myFree(&t_data, height, width);
    }
    else//缩小
    {
        alloc(&t_data, height / 2, width / 2);
        for (int i = 0; i < bitmapinfoheader.biHeight / 2; i++)
        {
            for (int j = 0; j < bitmapinfoheader.biWidth / 2; j++)
            {
                for (int k = 0; k < 3; k++)
                {
                    t_data[i][j][k] = data[i * 2][j * 2][k];
                }
            }
        }
        myFree(&data, height, width);
        alloc(&data, height / 2, width / 2);
        height /= 2;
        width /= 2;
        bitmapinfoheader.biHeight /= 2;
        bitmapinfoheader.biWidth /= 2;
        bitmapinfoheader.biSizeImage /= 4;
        for (int i = 0; i < bitmapinfoheader.biHeight; i++)
        {
            for (int j = 0; j < bitmapinfoheader.biWidth; j++)
            {
                for (int k = 0; k < 3; k++)
                {
                    data[i][j][k] = t_data[i][j][k];
                }
            }
        }
        myFree(&t_data, height, width);
    }
}


//图像裁剪的函数
void Image::Cut(int x1, int y1, int x2, int y2)
{
    int w = x2 - x1;
    int h = y2 - y1;
    unsigned char*** t = nullptr;
    alloc(&t, h, w);
    int i, j, k;
    for (i = y1; i < y2; i++)
    {
        for (j = x1; j < x2; j++)
        {
            for (k = 0; k < 3; k++)
            {
                t[i - x1][j - y1][k] = data[i][j][k];
            }
        }
    }
    myFree(&data, height, width);
    alloc(&data, h, w);
    for (i = 0; i < h; i++)
    {
        for (j = 0; j < w; j++)
        {
            for (k = 0; k < 3; k++)
            {
                data[i][j][k] = t[i][j][k];
            }
        }
    }
    myFree(&t, h, w);
    height = h;
    width = w;
    bitmapinfoheader.biWidth = w;
    bitmapinfoheader.biHeight = h;
    bitmapinfoheader.biSizeImage = h * w;
}


void Image::rotate()
{
    unsigned char*** t;
    alloc(&t, width, height);
    int i, j, k;
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            for (k = 0; k < 3; k++)
            {
                t[width - j - 1][i][k] = data[i][j][k];
            }
        }
    }
    myFree(&data, height, width);
    alloc(&data, width, height);
    for (i = 0; i < width; i++)
    {
        for (j = 0; j < height; j++)
        {
            for (k = 0; k < 3; k++)
            {
                data[i][j][k] = t[i][j][k];
            }
        }
    }
    myFree(&t, width, height);
    int temp;
    temp = width;
    width = height;
    height = temp;
    bitmapinfoheader.biWidth = width;
    bitmapinfoheader.biHeight = height;

}
//图像旋转的函数
void Image::Rotate(int degree)//图像旋转的函数（简单起见，旋转角度为90度的整数倍）
{
    int n = degree / 90;
    while (n)
    {
        n--;
        rotate();
    }
}
//求均值方差
void Image::Mean_Variance(float& m, float& var)//求图像的均值和方差，利用参数输出
{
    float sum = 0;
    float ave = 0;
    float vSum = 0;
    float vAve = 0;
    for (int i = 0; i < bitmapinfoheader.biHeight; i++)
    {
        for (int j = 0; j < bitmapinfoheader.biWidth; j++)
        {
            for(int k=0;k<3;k++)
            {
                sum+=data[i][j][k];
            }
        }
    }
    ave = sum / (bitmapinfoheader.biHeight * bitmapinfoheader.biWidth * 3);
    for (int i = 0; i < bitmapinfoheader.biHeight; i++)
    {
        for (int j = 0; j < bitmapinfoheader.biWidth ; j++)
        {
            for(int k=0;k<3;k++)
            {
                vSum += (data[i][j][k] - ave) * (data[i][j][k] - ave);
            }
        }
    }
    vAve = vSum / (bitmapinfoheader.biHeight * bitmapinfoheader.biWidth * 3);
    var= ave;
    m= vAve;
}

void Image::ReadBMP(const char* filename)
{
    FILE* fp = fopen(filename, "rb");
    if (NULL == fp)
    {
        exit(0);
    }
    fread(&bmpfileheader, sizeof(BMPFILEHEADER), 1, fp);
    fread(&bitmapinfoheader, sizeof(BITMAPINFOHEADER), 1, fp);
    height = bitmapinfoheader.biHeight;
    width = bitmapinfoheader.biWidth;
    if (width % 4 != 0)
    {
        width = width + 4 - width % 4;
    }
    int i, j, k;
    data = new unsigned char** [height];
    for (i = 0; i < height; i++)
    {
        data[i] = new unsigned char* [width];
        for (j = 0; j < width; j++)
        {
            data[i][j] = new unsigned char[3];
        }
    }
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            for (k = 0; k < 3; k++)
            {
                fread(&data[i][j][k], 1, 1, fp);
            }
        }
    }
    fclose(fp);
}
void Image::WriteBMP(const char* filename)
{
    FILE* fp = fopen(filename, "wb");
    if (fp == NULL)
    {
        exit(0);
    }
    fwrite(&bmpfileheader, sizeof(BMPFILEHEADER), 1, fp);
    fwrite(&bitmapinfoheader, sizeof(BITMAPINFOHEADER), 1, fp);
    int i, j, k;
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            for (k = 0; k < 3; k++)
            {
                fwrite(&data[i][j][k], 1, 1, fp);
            }
        }
    }
    fclose(fp);
}
void Image::myFree(unsigned char**** d, int h, int w)
{
    int i, j;
    for (i = 0; i < h; i++)
    {
        for (j = 0; j < w; j++)
        {
            delete[](*d)[i][j];
        }
        delete[](*d)[i];
    }
    delete[]*d;
}
void Image::alloc(unsigned char**** d, int h, int w)
{
    int i, j;
    *d = new unsigned char** [h];
    for (i = 0; i < h; i++)
    {
        (*d)[i] = new unsigned char* [w];
        for (j = 0; j < w; j++)
        {
            (*d)[i][j] = new unsigned char[3];
            for (int k = 0; k < 3; k++)
            {
                (*d)[i][j][k] = 0;
            }
        }
    }
}
void Image::gray()
{
    int i, j;
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            unsigned t = data[i][j][0] + data[i][j][1] + data[i][j][2];
            for (int k = 0; k < 3; k++)
            {
                data[i][j][k] = t / 3;
            }
        }
    }
}
void Image::Jpint(Image &a,int code)//一上下二左右
{
    int i,j,k;
    unsigned  char ***t;
    if(code)
    {
        if(a.width!=width)
        {
            exit(0);
        }
        else
        {
            alloc(&t,height+a.height,width);
            for(i=0;i<height+a.height;i++)
            {
                for(j=0;j<width;j++)
                {
                    for(k=0;k<3;k++)
                    {
                        if(i<height)
                        {
                            t[i][j][k]=data[i][j][k];
                        }
                        else
                        {
                            t[i][j][k]=a.data[i-height][j][k];
                        }
                    }
                }
            }
            myFree(&data,height,width);
            alloc(&data,height+a.height,width);
            for(i=0;i<height+a.height;i++)
            {
                for(j=0;j<width;j++)
                {
                    for(k=0;k<3;k++)
                    {
                        data[i][j][k]=t[i][j][k];
                    }
                }
            }
            myFree(&t,height+a.height,width);
            height=height+a.height;
            width=width;
            bitmapinfoheader.biHeight=height;
            bitmapinfoheader.biSizeImage=height*width;
        }
    }
    else
    {
        if(a.height!=height)
        {
            exit(0);
        }
        else
        {
            int w=a.width+width;
            alloc(&t,height,w);
            for(i=0;i<height;i++)
            {
                for(j=0;j<w;j++)
                {
                    for(k=0;k<3;k++)
                    {
                        if(j<width)
                        {
                            t[i][j][k]=data[i][j][k];
                        }
                        else
                        {
                            t[i][j][k]=a.data[i][j-width][k];
                        }
                    }
                }
            }
            myFree(&data,height,width);
            alloc(&data,height,w);
            for(i=0;i<height;i++)
            {
                for(j=0;j<w;j++)
                {
                    for(k=0;k<3;k++)
                    {
                        data[i][j][k]=t[i][j][k];
                    }
                }
            }
            myFree(&t,height,w);
            width=w;
            bitmapinfoheader.biWidth=w;
            bitmapinfoheader.biSizeImage=w*height;
        }
    }
}
int  Image::qbount(int a,int b,int c)
{
    int sum=a+b+c;
    int min=0;
    if(min<a)
    {
        min=a;
    }
    else if(min<b)
    {
        min=b;
    }
    else if(min<c)
    {
        min=c;
    }
    int max=0;
    if(max<a)
    {
        max=a;
    }
    else if(max<b)
    {
        max=b;
    }
    else if(max<c)
    {
        max=c;
    }
    return sum-min-max;

}

void Image::bianyuan()
{

    //灰度处理
    gray();
    //掩膜
    int a =0;
    int ave = 0, sum = 0;
    for (int i = 0; i < bitmapinfoheader.biHeight; i++) {
        for (int j = 0; j < bitmapinfoheader.biWidth; j++) {

            for (int k = 0; k < 3; k++) {
                sum += data[i][j][k];
            }
            ave = sum / 3;
            if (ave > 128) {
                for (int k = 0; k < 3; k++) {
                    data[i][j][k] = 255;
                }
            }
            else {
                for (int k = 0; k < 3; k++) {
                    data[i][j][k] = 0;
                }
            }
            sum = 0;
        }
    }

    int sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum6 = 0, sum7 = 0, sum8 = 0;
    for (int i = 1; i < bitmapinfoheader.biHeight - 1; i++) {
        for (int j = 1; j < bitmapinfoheader.biWidth - 1; j++) {

            for (int k = 0; k < 3; k++) {
                sum0 += data[i][j][k];
            }
            for (int k = 0; k < 3; k++) {
                sum1 += data[i - 1][j - 1][k];
            }
            for (int k = 0; k < 3; k++) {
                sum2 += data[i - 1][j][k];
            }
            for (int k = 0; k < 3; k++) {
                sum3 += data[i - 1][j + 1][k];
            }
            for (int k = 0; k < 3; k++) {
                sum4 += data[i][j - 1][k];
            }
            for (int k = 0; k < 3; k++) {
                sum5 += data[i][j + 1][k];
            }
            for (int k = 0; k < 3; k++) {
                sum6 += data[i + 1][j - 1][k];
            }
            for (int k = 0; k < 3; k++) {
                sum7 += data[i + 1][j][k];
            }
            for (int k = 0; k < 3; k++) {
                sum8 += data[i + 1][j + 1][k];
            }
            if (sum1 + sum2 + sum3 + sum4 + sum5 + sum6 + sum7 + sum8 == 8 * sum0) {
                for (int h = 0; h < 3; h++)
                {
                    data[i][j][h] = 0;
                }
            }

        }
    }

}
